package com.tianqu.tms.core.webservice;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;

import com.tianqu.tms.core.base.TxController;
import com.tianqu.tms.core.exception.TmsDaoException;
import com.tianqu.tms.core.exception.TransactionException;
import com.tianqu.tms.core.util.CopyFile;
import com.tianqu.tms.core.util.DateUtil;
import com.tianqu.tms.core.util.ImageUtils;
import com.tianqu.tms.core.util.JCifsUtil;
import com.tianqu.tms.core.util.MD5Util;
import com.tianqu.tms.core.util.Registry;
import com.tianqu.tms.core.util.StringUtil;
import com.tianqu.tms.core.util.TmsConstants;
import com.tianqu.tms.core.util.UrlBase64Coder;
import com.tianqu.tms.core.util.enums.BarCodeType;
import com.tianqu.tms.core.util.enums.CarRegisterStatus;
import com.tianqu.tms.core.util.enums.GateResult;
import com.tianqu.tms.core.util.enums.IdentifyTypes;
import com.tianqu.tms.core.util.enums.PlateNumberTypes;
import com.tianqu.tms.core.util.enums.ThreadStatus;
import com.tianqu.tms.core.webservice.weichat.api.MobileMessage;
import com.tianqu.tms.core.webservice.weichat.api.PullingExecutor;
import com.tianqu.tms.core.webservice.weichat.api.WeChatMqApi;
import com.tianqu.tms.core.webservice.weichat.api.rpc.TransferDataSyn000210Bo;
import com.tianqu.tms.core.webservice.weichat.api.rpc.TransferDataSyn000601Bo;
import com.tianqu.tms.core.webservice.weichat.api.rpc.TransferDataSyn30300Bo;
import com.tianqu.tms.core.webservice.weichat.api.rpc.TransferDataSyn30400Bo;
import com.tianqu.tms.dao.TmsDao;
import com.tianqu.tms.dao.TransferAcceptedInfoDaoImp;
import com.tianqu.tms.dto.TmsMarketCarFinancialDto;
import com.tianqu.tms.dto.TmsMarketCarFinancialParam;
import com.tianqu.tms.dto.TransferAcceptedInfoDto;
import com.tianqu.tms.entity.Car;
import com.tianqu.tms.entity.Codes;
import com.tianqu.tms.entity.MarketCarGateInfo;
import com.tianqu.tms.entity.Member;
import com.tianqu.tms.entity.TmsFinancial;
import com.tianqu.tms.www.api.form.InputParam;
import com.tianqu.tms.www.car.action.CarImportExportMonitoringAjaxAction;

public class TmsCarGateService {
	//
	private org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger.getLogger(TmsCarGateService.class);
	ConcurrentHashMap <String, String> filterMap = new ConcurrentHashMap<String, String>();
	
	/**
	 * 收费门禁逻辑
	 * @param plateNum
	 * @param rfid
	 * @param cameraIp
	 * @param picPath
	 * @param gateNo
	 * @param plateColor
	 * @param vehicleColor
	 * @return
	 */
	public String getChargePermission(InputParam request) {
		String CHARGE_FLAG = "1";
		String NO_CHARGE_FLAG = "0";
		String plateNum = request.getPlateNum();
		String rfid = request.getRfid();
//		if(StringUtil.isNullOrBlank(plateNum)) return r;
		//
		TxController tx = TxController.getTxController();
		
		try {
//			//一、根据车牌号码判定车辆是否是办理过户业务车辆
//			TransferAcceptedInfoDaoImp transferAcceptedInfoDao = (TransferAcceptedInfoDaoImp) TransferAcceptedInfoDaoImp.getInstance(TmsDao.TMS_TRANSFER_ACCEPTED_INFO);
//			TransferAcceptedInfoDto dto = transferAcceptedInfoDao.getTransferAcceptedInfoByLicenseplate(plateNum);
//			if(dto == null) transferAcceptedInfoDao.getTransferAcceptedInfoByLicenseplate(plateNum,true);
//			if(dto == null) return r;
			
			//二、判定车辆是否当天是否有办理业务
//			String freeStopHour = (String)Registry.getConfig("freeStopHour");
//			Timestamp acceptedInsertTime = dto.getInsertTime();
//			Date currentDate = new Date();
//			//
//			TransferProcessHistoryDao transferProcessHistoryDao = (TransferProcessHistoryDao) TmsDao.getInstance(TmsDao.TMS_TRANSFER_PROCESS_HISTORY);
//			List<TransferProcessHistoryDto> list = new ArrayList<TransferProcessHistoryDto>();
//			//
//			if(dto.getStatus()!=0 && dto.getStatus()!=16){
//				list = transferProcessHistoryDao.loadTransferProcessHistoryBySerial(dto.getSerial());
//				if(list.size() >0){
//					TransferProcessHistoryDto history = list.get(1);
//					if(getIntervalDays(history.getInsertTime(),new Date()) == 0) return freeStopHour;
//				}
//			}else if(dto.getStatus() == 16 && getIntervalDays(acceptedInsertTime,currentDate) <= 3){
//				list = transferProcessHistoryDao.loadTransferProcessHistoryBySerial(dto.getSerial());
//				if(list.size() >0){
//					TransferProcessHistoryDto history = list.get(1);
//					if(getIntervalDays(history.getInsertTime(),new Date()) <= 3) return freeStopHour;
//				}
//			}else{
//				return r;
//			}
			if(StringUtil.isNotBlank(plateNum)) {
				 //1）车辆是否是特权车判定：通过车牌号码（licensePlate）匹对识别的车牌号码（截取前两位，只留后5位或6位进行匹对） +有效状态（registerStatus）为“1：有效”，到库存特权车辆信息表（tms_market_car_privilege）查询；如果有符合条件的数据，表明此车辆为特权车
				 Car privilegeCar = Car.getInstance().findPrivilegeCarByTempLicensePlate(plateNum,PlateNumberTypes.PLATE_NUMBER.getValue());//查询特权车
				 if(privilegeCar != null) return NO_CHARGE_FLAG;
				 
				 //2）库存车辆判定：通过车牌号码（licensePlate）匹对识别的车牌号码（截取前两位，只留后5位或6位进行匹对），到库存车辆信息表（TMS_MARKET_CAR_INFO）查询；如果查询出来多条，只取更新时间（updateTime）为最新的一条记录
				 Car car = Car.getInstance().findCarById(plateNum, PlateNumberTypes.PLATE_NUMBER);
				 if(car!=null) {
					 if(car.getRegisterStatus()!=3 && car.getRegisterStatus()!=4) return NO_CHARGE_FLAG;
					 if((car.getRegisterStatus()==3 || car.getRegisterStatus()==4) && daysBetween(car.getEnterTime(),new Date()) == 0) return NO_CHARGE_FLAG;
					 if((car.getRegisterStatus()==3 || car.getRegisterStatus()==4) && daysBetween(car.getEnterTime(),new Date()) != 0) return CHARGE_FLAG;
				 }
				 
				 //3）用车辆旧的车牌来进行库存车辆判定：通过旧车牌号码（newLicensePlate）匹对识别的车牌号码（截取前两位，只留后5位或6位进行匹对）+ 换车牌时间（newLicensePlate）
				 //比当前系统时间小15天以内，到库存车辆信息表（TMS_MARKET_CAR_INFO）查询；如果查询出来多条，只取更新时间（updateTime）为最新的一条记录
				 car = Car.getInstance().findCarByNewLicensePlate(plateNum);
				 if(car!=null) {
					 if(car.getRegisterStatus()!=3 && car.getRegisterStatus()!=4) return NO_CHARGE_FLAG;
					 if((car.getRegisterStatus()==3 || car.getRegisterStatus()==4) && daysBetween(car.getEnterTime(),new Date()) == 0) return NO_CHARGE_FLAG;
					 if((car.getRegisterStatus()==3 || car.getRegisterStatus()==4) && daysBetween(car.getEnterTime(),new Date()) != 0) return CHARGE_FLAG;
				 }
				 
				//4）过户车辆判定：通过车牌号码（licensePlate）匹对识别的车牌号码（截取前两位，只留后5位或6位进行匹对），到过户业务基本信息表（tms_transfer_accepted_info）查询；如果查询出来多条，只取更新时间（updateTime）为最新的一条记录
				TransferAcceptedInfoDaoImp transferAcceptedInfoDao = (TransferAcceptedInfoDaoImp) TransferAcceptedInfoDaoImp.getInstance(TmsDao.TMS_TRANSFER_ACCEPTED_INFO);
				TransferAcceptedInfoDto acceptedInfo = transferAcceptedInfoDao.getTransferAcceptedInfoByLicenseplate(plateNum);
				if(acceptedInfo!=null) {
					 if(daysBetween(acceptedInfo.getInsertTime(),new Date()) == 0) return NO_CHARGE_FLAG;
					 else if(daysBetween(acceptedInfo.getInsertTime(),new Date()) == 0)  return CHARGE_FLAG;
				}
			}else if(StringUtil.isNotBlank(rfid)) {
				 Car privilegeCar = Car.getInstance().findPrivilegeCarByTempLicensePlate(rfid,PlateNumberTypes.TEMP_PLATE_NUMBER.getValue());//查询特权车
				 if(privilegeCar!=null) return NO_CHARGE_FLAG;
				 
				 Car car = Car.getInstance().findCar(rfid,0);
				 if(car!=null) {
					 if(car.getRegisterStatus()!=3 && car.getRegisterStatus()!=4) return NO_CHARGE_FLAG;
					 if((car.getRegisterStatus()==3 || car.getRegisterStatus()==4) && daysBetween(car.getEnterTime(),new Date()) == 0) return NO_CHARGE_FLAG;
					 if((car.getRegisterStatus()==3 || car.getRegisterStatus()==4) && daysBetween(car.getEnterTime(),new Date()) != 0) return CHARGE_FLAG;
				 }
			}
		} catch (Exception e) {
			LOGGER.error("chargePermission error", e);
		}finally {
			try { tx.commit(); } catch (TransactionException e) { }
		}
		return CHARGE_FLAG;
	}

	/**
	 * 非收费门禁逻辑
	 * @param plateNum
	 * @param rfid 易碎贴编号
	 * @param cameraIp
	 * @param picPath
	 * @param gateNo
	 * @return
	 */
	public String getPermission(InputParam request) {
		String gateResult = GateResult.SUCCESS.getValue();
		String threadStatus ="";
		String gateWayNo = "";
		//jdbc
		TxController tx = TxController.getTxController();
		//
		try {
			tx.begin();
			
			String plateNum = request.getPlateNum(); 
			String rfid = request.getRfid(); 
			String cameraIp = request.getCameraIp();
			String picPath = request.getPicPath();
			String picData = request.getPicData();
			int gateNo = request.getDeviceId();
			int plateColor = 0;
			int vehicleColor = 0;
			try {
				if(StringUtils.isNumeric(request.getPlateColor())) plateColor = Integer.parseInt(request.getPlateColor());
				if(StringUtils.isNumeric(request.getVehicleColor())) vehicleColor = Integer.parseInt(request.getVehicleColor());
			} catch (Exception e) {}
			String carSerial ="";
			boolean isOutGateway = isOutGateway(gateNo);
			boolean isInGateway = !isOutGateway;
			String picName = MD5Util.getMD5String(CopyFile.getFileNameNoEx(picPath))+".jpg";
			//
			String gateNoStr = "00";
			if(gateNo>0 && gateNo<10){gateNoStr = "0"+gateNo;}
			else gateNoStr = gateNo+"";
			gateWayNo = TmsConstants.MARKET_NO + gateNoStr;
			String isFilter = filterMap.get(gateWayNo);
			if(StringUtil.isNotBlank(isFilter)){
				LOGGER.debug("ignore the request,plateNum:"+plateNum +" rfid:"+rfid +" gateNo:"+gateNo);
				return GateResult.RESULT_06.getValue();
			}else{
				filterMap.put(gateWayNo, gateWayNo);
			}
			//
			int debug = 0;
			int updateUsedPort = 0;
			int threadType = 1;// 1：号牌识别、2：易碎贴识别、3：人工处理、4：旧号牌识别
			Member member = new Member();
			Car car = null,privilegeCar = null;//特权车
			String identifyType = (String)Registry.getConfig("gateType");//系统设定识别方式
			boolean isCheck = isCheckOn(gateWayNo);
			//无法识别：如果识别系统传过来的车牌号码 和 易碎贴编号都是空的
			if(StringUtil.isNullOrBlank(plateNum) && StringUtil.isNullOrBlank(rfid)){
				LOGGER.error("invalid parameter. gateNo:"+gateNo);
				return GateResult.RESULT_06.getValue();
			}else{
				//如果传入的车牌号码有值 并且 识别方式设置为"2：车牌识别、3：易碎贴+车牌识别"情况，根据下面逻辑查询车辆信息
				if(StringUtil.isNotBlank(plateNum) && (IdentifyTypes.TYPE_2.getValue().equals(identifyType) || IdentifyTypes.TYPE_3.getValue().equals(identifyType))){
					threadType = 1; privilegeCar = Car.getInstance().findPrivilegeCarByTempLicensePlate(plateNum,PlateNumberTypes.PLATE_NUMBER.getValue());//查询特权车
					if(privilegeCar == null){
						car = Car.getInstance().findCarById(plateNum, PlateNumberTypes.PLATE_NUMBER);
						if(car == null){
							threadType = 4; car = Car.getInstance().findCarByNewLicensePlate(plateNum);
						} 
					} 
				}
				
				//如果传入的易碎贴编号有值 并且 系统配置的识别方式设置为“1：易碎贴识别、3：易碎贴+车牌识别”情况，根据下面逻辑查询车辆信息
				if(privilegeCar == null && car == null && StringUtil.isNotBlank(rfid) && (IdentifyTypes.TYPE_1.getValue().equals(identifyType) || IdentifyTypes.TYPE_3.getValue().equals(identifyType))){
					threadType = 2; privilegeCar = Car.getInstance().findPrivilegeCarByTempLicensePlate(rfid,PlateNumberTypes.TEMP_PLATE_NUMBER.getValue());//查询特权车
					if(privilegeCar == null) car = Car.getInstance().findCarByTempLicensePlate(rfid);
				}
				
				if(privilegeCar!=null){
					debug = 2; return GateResult.SUCCESS.getValue();//特权车辆直接通过
				}
				
				//车辆出库时候车辆的库存登记已经取消：如果车辆存在并且库存状态为"3：取消  、4：存档" ， 并且当前传入道闸编号为双号（出口），那么进行如下操作：
				if(car!=null && isOutGateway && (car.getRegisterStatus() == CarRegisterStatus.OVERDUE.getValue() || car.getRegisterStatus() == CarRegisterStatus.ARCHIVE.getValue())) {
					threadStatus = ThreadStatus.RESULT_09.getValue();
					if(isCheck) gateResult = GateResult.RESULT_01.getValue();
					else gateResult = GateResult.SUCCESS.getValue();
				}else if(car == null ||(isInGateway && car != null && (car.getRegisterStatus() == CarRegisterStatus.OVERDUE.getValue() || car.getRegisterStatus() == CarRegisterStatus.ARCHIVE.getValue()))){
					//3、未办理库存登记：如果根据“根据车牌号码/易碎贴编号获取车辆信息”的查询没有获得对应车辆信息情况，或者 车辆存在并且库存状态为"3：取消  、4：存档" 并且 当前传入道闸编号为单号（入口）
					threadStatus = ThreadStatus.RESULT_02.getValue();
					if(isCheck){
//						String isRelatePake = (String)Registry.getConfig("isRelatePake");
//						if("off".equals(isRelatePake)) gateResult = GateResult.RESULT_02.getValue();
//						else if("on".equals(isRelatePake)) gateResult = GateResult.RESULT_09.getValue();
//						else gateResult = GateResult.RESULT_02.getValue();
						gateResult = GateResult.RESULT_02.getValue();
					}else{
						gateResult = GateResult.SUCCESS.getValue();
					}
					debug = 3;
				}else{//库存统计
					//金融管控信息查询 
					TmsMarketCarFinancialParam param = new TmsMarketCarFinancialParam();
					if(StringUtil.isNotBlank(plateNum)) param.setLicensePlate(plateNum);
					else if(StringUtil.isNotBlank(rfid)) param.setTempLicensePlate(rfid);
					List<TmsMarketCarFinancialDto> marketCarFinancialList = TmsFinancial.getInstance().findTmsMarketCarFinancial(param);
					//
					member = member.findMemberInfoByMemId(String.valueOf(car.getMemberId()));
					HashMap<String, String> identityRangeMap = getIdentityRange(member.getIdentityRange());
					HashMap<String, String> tempIdentityRangeMap = getIdentityRange(member.getTmpIdentityRange());
					Timestamp currentTime = new Timestamp(System.currentTimeMillis());
					//车辆没有登记完成：如果车辆存在并且库存状态为"5：登记" ， 并且当前传入道闸编号为单号（入口） ，并且车辆录入状态（entryStatus）为“1：未采集完成”
					if(isInGateway && car.getRegisterStatus() == CarRegisterStatus.REGISTER.getValue() && car.getEntryStatus() == 1){
						if(isCheck) gateResult = GateResult.RESULT_02.getValue();
						else gateResult = GateResult.SUCCESS.getValue();
						threadStatus = ThreadStatus.RESULT_02.getValue();
						
						debug = 14;
					}else if(BarCodeType.TYPE_1.getValue() == car.getBarCodeNum() && isComparedResult(currentTime,car,1) && (marketCarFinancialList.size() == 0 || marketCarFinancialList.get(0).getStatus() == 2)){
						//7、车辆被挂起：如果车辆存在并且车辆挂起状态为“1：是” 并且 （当前系统时间小于临时进出开始时间（tmpStorageTime）或者 																																						
						//大于 临时进出结束时间（tmpEnterTime）或者临时进出开始时间（tmpStorageTime）与 临时进出结束时间（tmpEnterTime）为空），
						//并且车辆在车辆金融管控信息表（tms_market_car_financial）不存在 或者存在但是 其关联的车辆金融管控信息表的监管状态（status）为”2：取消监管“，那么进行如下操作：																																	
						if(isCheck) gateResult = GateResult.RESULT_03.getValue();
						else gateResult = GateResult.SUCCESS.getValue();
						threadStatus = ThreadStatus.RESULT_03.getValue();
						debug = 6;
					}else if((isInGateway && car.getRegisterStatus() == CarRegisterStatus.IN_STORAGE.getValue())){//车辆库存状态错误（入库情况）：如果车辆存在并且库存状态为"1：已入库" ， 并且当前传入道闸编号为单号（入口）
						if(isCheck)gateResult = GateResult.RESULT_04.getValue();
						else gateResult = GateResult.SUCCESS.getValue();
						threadStatus = ThreadStatus.RESULT_04.getValue();
						
						debug = 4;
					}else if(isOutGateway && car.getRegisterStatus() == CarRegisterStatus.OUT_STORAGE.getValue()){//车辆库存状态错误（出库情况）：如果车辆存在并且库存状态为“2：已出库”
//						if(isCheck) gateResult = GateResult.RESULT_04.getValue();
						if(isCheck) gateResult = GateResult.RESULT_06.getValue();
						else gateResult = GateResult.SUCCESS.getValue();
//						threadStatus = ThreadStatus.RESULT_04.getValue();
						threadStatus = ThreadStatus.RESULT_06.getValue();
						debug = 5;
					}else if(StringUtil.isNullOrBlank(identityRangeMap.get(gateWayNo)) && StringUtil.isNullOrBlank(tempIdentityRangeMap.get(gateWayNo))){//7、识别道闸不在车辆登记的道闸识别范围内
//						if(isCheck) gateResult = GateResult.RESULT_03.getValue();
						if(isCheck) gateResult = GateResult.RESULT_08.getValue();
						else gateResult = GateResult.SUCCESS.getValue();
//						threadStatus = ThreadStatus.RESULT_03.getValue();
						threadStatus = ThreadStatus.RESULT_11.getValue();
						debug = 7;
					}else if(isOutGateway && !StringUtil.isNullOrBlank(tempIdentityRangeMap.get(gateWayNo)) && isCheckTmpIdentityTime(car)){//8、识别道闸位车辆登记的临时有效道闸识别范围内 并且 超过指定时间出库情况
						//
//						if(isCheck) gateResult = GateResult.RESULT_03.getValue();
						if(isCheck) gateResult = GateResult.RESULT_08.getValue();
						else gateResult = GateResult.SUCCESS.getValue();
//						threadStatus = ThreadStatus.RESULT_03.getValue();
						threadStatus = ThreadStatus.RESULT_11.getValue();
						 
						//2）库存信息处理
						car.setBarCodeNum(1);//挂起
						car.updateMarketCarInfo(car);
						//
						String pushContent = getPushContent(car,member);
						car.setSerial(car.getSerial());
						car.setHandleType(1);
						car.setIsPush(1);
						car.setPushContent(pushContent);
						car.setUpdateUserId(1);
						SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式 			
						String updataTime = DateUtil.getCurrentTime();
						car.setUpdateTime(df.parse(updataTime));
						car.insertCarHandleInfo(car);
						//api 201
						callApiTransferDataSyn210(car,member);
						debug = 8;
					}else{//库存处理
						
						//入库
						//会员车位数已满：（如果车辆存在，并且在会员表里面找不到会员信息） 或者 （如果车辆存在，当前传入道闸编号为单号（入口），
						if(member.getMemId() < 1  || (isInGateway && member.getUsedCarPort() >= member.getCarPort())){
							if(isCheck){
								gateResult = GateResult.RESULT_05.getValue();
								debug = 9;
							}else{
								//更新库存
								if(isInGateway){
									member.updateUsedCarPort(car.getMemberId(),member.getUsedCarPort(), 1, TmsConstants.SYSTEM_OPERATOR_ID,"CarGateway");
									//
									car.setRegisterStatus(CarRegisterStatus.IN_STORAGE.getValue());
									car.updateCarRegisterStatus(car.getSerial(),car.getRegisterStatus(),TmsConstants.SYSTEM_OPERATOR_ID);
									updateUsedPort = 1;
								}
								//
								gateResult = GateResult.SUCCESS.getValue();
								debug = 10;
							}
						}else if(isInGateway){
							//更新库存
							int usedCarPort = member.getUsedCarPort() + 1;
							member.updateUsedCarPort(car.getMemberId(),member.getUsedCarPort(), 1, TmsConstants.SYSTEM_OPERATOR_ID,"CarGateway");
							//修改状态
							car.setRegisterStatus(CarRegisterStatus.IN_STORAGE.getValue());
							car.updateCarRegisterStatus(car.getSerial(),car.getRegisterStatus(),TmsConstants.SYSTEM_OPERATOR_ID);
							// 3、【TMS】入库登记/接口入库登记 =》【车代办】同步
							MobileMessage message = new MobileMessage();
							message.putValue("Serial", car.getSerial());
							message.setMessage("【TMS】入库登记/接口入库登记 =》【车代办】同步,Serial为#Serial#");

							TransferDataSyn30300Bo api = new TransferDataSyn30300Bo();
							api.setMobileMessage(message);
							api.setRegisterStatus(car.getRegisterStatus());
							api.setSerial(car.getSerial());
							api.setUsedCarPort(usedCarPort);
							api.setMarketNo(TmsConstants.MARKET_NO);
							PullingExecutor.getInstance().submit(api);
							debug = 11;
							updateUsedPort = 1;
						}

						
						//出库
						//贷款车辆出库：如果车辆存在，并且当前传入道闸编号为双号（出口） ，并且车辆挂起状态为“1：是” 并且 （当前系统时间小于临时进出开始时间（tmpStorageTime）或者 
						//大于 临时进出结束时间（tmpEnterTime）或者临时进出开始时间（tmpStorageTime）与 临时进出结束时间（tmpEnterTime）为空），并且车辆在车辆金融管控信息表（tms_market_car_financial）存在，
						//并且 其关联的车辆金融管控信息表的监管状态（status）为”1：监管中“，那么进行如下操作：
						if(car!=null 
								&& isOutGateway 
								&& car.getBarCodeNum() == BarCodeType.TYPE_1.getValue() 
								&& isComparedResult(currentTime,car,1)  
								&& (marketCarFinancialList !=null && marketCarFinancialList.size() > 0 && marketCarFinancialList.get(0).getStatus() == 1)) {
							if(isCheck) gateResult = GateResult.RESULT_07.getValue();
							else gateResult = GateResult.SUCCESS.getValue();
							
							threadStatus = ThreadStatus.RESULT_10.getValue();
							debug = 16;
						}
						
						
						if(isOutGateway && car.getRegisterStatus() == CarRegisterStatus.IN_STORAGE.getValue() && member.getUsedCarPort() > 0){
							//更新库存
							int increment = -1;
							if (member.getUsedCarPort() < 1) increment = 0;
							member.updateUsedCarPort(car.getMemberId(),member.getUsedCarPort(), increment, TmsConstants.SYSTEM_OPERATOR_ID,"CarGateway");
							//修改状态
							car.setRegisterStatus(CarRegisterStatus.OUT_STORAGE.getValue());
							car.updateCarRegisterStatus(car.getSerial(),car.getRegisterStatus(),TmsConstants.SYSTEM_OPERATOR_ID);
							// 4、【TMS】出库登记/接口出库登记 =》【车代办】同步
							MobileMessage message = new MobileMessage();
							message.putValue("Serial", car.getSerial());
							message.setMessage("【TMS】出库登记/接口出库登记 =》【车代办】同步,Serial为#Serial#");
							TransferDataSyn30400Bo api = new TransferDataSyn30400Bo();
							api.setMobileMessage(message);
							api.setRegisterStatus(car.getRegisterStatus());
							api.setSerial(car.getSerial());
							api.setUsedCarPort(member.getUsedCarPort() + increment);
							api.setMarketNo(TmsConstants.MARKET_NO);
							PullingExecutor.getInstance().submit(api);
							debug = 12;
							updateUsedPort = 1;
						}else if(isOutGateway && car.getRegisterStatus() == CarRegisterStatus.REGISTER.getValue()){////# 如果对应库存车辆信息表（tms_market_car_info）的车辆库存状态（registerStatus）为“6：登记” 并且 传入道闸编号为双号（出口），那么进出状态（threadStatus）更新为“8（库内登记）“
							car.updateCarRegisterStatus(car.getSerial(),CarRegisterStatus.OUT_STORAGE.getValue(),TmsConstants.SYSTEM_OPERATOR_ID);
						}
						 
						//出库情况（当前传入道闸编号为双号（出口）），并且 车辆录入状态（entryStatus）为“2：快速登记”
						if(isOutGateway && car.getEntryStatus() == 2){
							//更新 库存车辆信息表（tms_market_car_info）
							car.updateChargeStartDateBySerial(car.getSerial(),null);
						}
					}
                    
					//如果车辆存在并且车辆挂起状态为“1：是” 并且 当前系统时间大于或者等于临时进出开始时间（tmpStorageTime）并且 小于或者等于临时进出结束时间（tmpEnterTime）
					if(BarCodeType.TYPE_1.getValue() == car.getBarCodeNum() && isComparedResult(currentTime,car,2)){
						//挂起车辆进出时进行推送通知
						String memberId = "";
						if(marketCarFinancialList!=null && marketCarFinancialList.size()>0 && marketCarFinancialList.get(0).getStatus() == 1) {
							memberId = Registry.getConfigFromDb(TmsConstants.BANKING);
						}else {
							memberId = Registry.getConfigFromDb(TmsConstants.MANAGER);
						}
						
						String pushContent = "";
						if(isInGateway){
							pushContent = getPushContent(car,1);
						}else if(isOutGateway){
							pushContent = getPushContent(car,2);
						}
						//接口编号：601；【TMS_web】=》微信终端
						TransferDataSyn000601Bo transferDataSyn000601Bo = new TransferDataSyn000601Bo();
						if(StringUtil.isNotBlank(memberId)) transferDataSyn000601Bo.setMemberId(Integer.valueOf(memberId));
						else transferDataSyn000601Bo.setMemberId(0);
						transferDataSyn000601Bo.setPushContent(pushContent);			
						WeChatMqApi.getInstance().call(transferDataSyn000601Bo);
						debug = 13;
					}
					
					//五、金融车辆进出时进行推送通知
					if(marketCarFinancialList.size() == 0 || marketCarFinancialList.get(0).getStatus() == 1) {
						String memberId = Registry.getConfigFromDb(TmsConstants.BANKING);
						String pushContent = "";
						if(isInGateway){
							pushContent = getFinancialPushContent(car,1);
						}else if(isOutGateway){
							pushContent = getFinancialPushContent(car,2);
						}
						//接口编号：601；【TMS_web】=》微信终端
						TransferDataSyn000601Bo transferDataSyn000601Bo = new TransferDataSyn000601Bo();
						if(StringUtil.isNotBlank(memberId)) transferDataSyn000601Bo.setMemberId(Integer.valueOf(memberId));
						else transferDataSyn000601Bo.setMemberId(0);
						transferDataSyn000601Bo.setPushContent(pushContent);			
						WeChatMqApi.getInstance().call(transferDataSyn000601Bo);
						debug = 17;
					}
				}
			}
			if(car!=null){
				carSerial = car.getSerial();
				if(GateResult.SUCCESS.getValue().equals(gateResult)) {
					if(vehicleColor!=0 && car.getColor() != vehicleColor){
						debug = 14;
					    threadStatus = ThreadStatus.RESULT_07.getValue();
					} else if(isOutGateway && car.getRegisterStatus() == CarRegisterStatus.REGISTER.getValue()) {
						debug = 15;
						threadStatus = ThreadStatus.RESULT_08.getValue();
					}
				}
			}
			
			//insert history
			int checkFlag = isCheck?2:1; 
			String webPicPath = ImageUtils.getImageUrl(Registry.getConfig(TmsConstants.GATE_PIC_MODULE_KEY)) + picName;
			if(StringUtil.isNullOrBlank(threadStatus)) threadStatus = gateResult;
			createHistory(plateNum,rfid,vehicleColor,plateColor, carSerial, threadType, cameraIp, webPicPath, Integer.parseInt(gateWayNo), checkFlag, threadStatus);
			//
			CarImportExportMonitoringAjaxAction.push(webPicPath,gateWayNo,plateNum, rfid, carSerial, Integer.parseInt(threadStatus), threadType, checkFlag);
			//
			String log = "CarGateInfo memberId:"+member.getMemId()+
					" threadType:"+threadType+
					" plateNum:"+plateNum+
					" carSerial:"+carSerial +
					" threadStatus:"+threadStatus+
					" gateResult:"+gateResult+
					" processCase:"+debug+
					" checkFlag:"+String.valueOf(checkFlag)+
					" updateUsedPort:"+updateUsedPort;
			LOGGER.debug(log);
			
			//copy pic
			if(StringUtil.isNotBlank(picPath) && StringUtil.isNotBlank(picData)){
				generateImage(picData,picName);
			}else{
				copyPic(picPath,picName);
			}
		} catch (Exception e) {
			LOGGER.error("AbstractTmsCarGateService error,", e);
			gateResult = GateResult.RESULT_02.getValue();
		}finally {
			filterMap.remove(gateWayNo);
			try { tx.commit(); } catch (TransactionException e) {
				LOGGER.error("AbstractTmsCarGateService error,", e);
				gateResult = GateResult.RESULT_02.getValue();
				//
				try {
					tx.rollback();
				} catch (TransactionException ex) {
					LOGGER.error("rollback error,", ex);
				}
			}
		}
		return gateResult;
	}
	
	
	private void generateImage(String picData,String picName){
		try {
			String picPath = ImageUtils.getImageDirectoryPath(Registry.getConfig(TmsConstants.GATE_PIC_MODULE_KEY)) + picName;
			ImageUtils.generateImageBase64(UrlBase64Coder.decode(picData),picPath);
		} catch (Exception e) {
			LOGGER.error("rollback error,", e);
		}
		
	}
	
	private void copyPic (String picPath,String picName){
		if (!StringUtil.isNullOrBlank(picPath)) {
			//fix bug20170209
			String remotePath = Registry.getConfig(TmsConstants.GATE_PIC_SERVER_KEY) + "\\" + picPath;
			
			boolean r =  JCifsUtil.getRemoteFile(
							Registry.getConfig(TmsConstants.GATE_PIC_SERVER_USERNAME_KEY),
							Registry.getConfig(TmsConstants.GATE_PIC_SERVER_PASSWORD_KEY), 
							remotePath.replace("\\", "/"),
							ImageUtils.getImageDirectoryPath(Registry.getConfig(TmsConstants.GATE_PIC_MODULE_KEY)),
							picName);
			if (!r) LOGGER.error("failed to copy picture,patch:" + remotePath);
		}
	}

	private void createHistory(String licensePlate,String tempLicensePlate,int color,int licenseColor, String carSerial, int type, String cameraIp, String picPath, int gateNo, int checkFlag, String result) throws TmsDaoException {
		MarketCarGateInfo inf = new MarketCarGateInfo();
		inf.setLicensePlate(licensePlate);
		inf.setSerial(carSerial);
		inf.setGateId(gateNo);// 道闸编号
		inf.setGateType(Codes.getInstance().getItemValueByItemIdAndItemCode(122, gateNo));// 道闸类型
		inf.setLocatedIP(cameraIp);// 道闸相机ip
		inf.setCarPhoto(picPath);// 车辆照片路径
		inf.setThreadType(type);// 进出方式
		inf.setThreadStatus(Integer.valueOf(result));// 进出状态
		inf.setTempLicensePlate(tempLicensePlate);
		inf.setCheckFlag(checkFlag);// 过滤状态
		inf.setColor(color);
		inf.setLicenseColor(licenseColor);
		inf.setUpdateUserId(TmsConstants.SYSTEM_OPERATOR_ID);// 更新用户
		MarketCarGateInfo.getInstance().insertGateInfo(inf);
	}
 

	/**
	 * 开关
	 * @param gateNo
	 * @return
	 */
	private boolean isCheckOn(String gateNo) {
		boolean r = true;// on/off/hh:mm-hh:mm
		String value = Registry.getConfigFromDb("gateSwitch_"+gateNo);;
		try {
			if (StringUtil.isNullOrBlank(value)) return r;

			if ("on".equalsIgnoreCase(value)) {
				r = true;
			} else if ("off".equalsIgnoreCase(value)) {
				r = false;
			} else {
				String startTime = value.split("-")[0];
				int startHour = Integer.valueOf(startTime.split(":")[0]);
				int startSecond = Integer.valueOf(startTime.split(":")[1]);
				//
				String endTime = value.split("-")[1];
				int endHour = Integer.valueOf(endTime.split(":")[0]);
				int endSecond = Integer.valueOf(endTime.split(":")[1]);
				//
				Date start = getDateTime(startHour, startSecond);
				Date end = getDateTime(endHour, endSecond);
				Date current = new Date();
				//
				if (start.before(current) && end.after(current)) r = true;
				else r = false;
			}
		} catch (Exception e) {
			LOGGER.error("isSwitchOn", e);
			r = true;
		}
		return r;
	}
	
	
	private static boolean isOutGateway(int gateNo) {
		return gateNo % 2 == 0;
	}

	private Date getDateTime(int hour, int second) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, hour);
		cal.set(Calendar.SECOND, second);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	public static int daysBetween(Date date1, Date date2) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date1);
		long time1 = cal.getTimeInMillis();
		cal.setTime(date2);
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}
	
	public static int getIntervalDays(Date fDate, Date oDate) {
		if (null == fDate || null == oDate) { return -1; 	}
		long intervalMilli = oDate.getTime() - fDate.getTime();
		return (int) (intervalMilli / (24 * 60 * 60 * 1000));
	}
	
	public static int getIntervalTime(Date fDate, Date oDate) {
		if (null == fDate || null == oDate) { return -1; 	}
		return  (int) ((fDate.getTime() - oDate.getTime()) / (1000 * 60));
	}
	
	private HashMap getIdentityRange(String identityRange){
		HashMap m = new HashMap();
		if (StringUtil.isNullOrBlank(identityRange)) return m;
		String[] tmp = identityRange.split(",");
		for (int i = 0; i < tmp.length; i++)  m.put(tmp[i], "1");
		return m;
	}
	
    private String getPushContent(Car car,Member member){
    	String tempIdentityTime = getTmpIdentityTime() +"";
    	String intervalTime = getIntervalTime(car.getInsertTime(),new Date()) +"";
    	String content = "";
    	if(StringUtil.isNotBlank(car.getLicensePlate())){
    		content = "【车辆挂起通知】"+member.getShortName()+"登记的车牌号码为"+car.getLicensePlate()+"的+"+car.getCarName()+"，没有在规定的"+tempIdentityTime+"分钟内从临时展厅出库，被系统自动挂起，请到出入库进行解挂。超出规定时间"+intervalTime+"分钟。";
    	}else if(StringUtil.isNullOrBlank(car.getVin())){
    		content = "【车辆挂起通知】"+member.getShortName()+"登记的车架号后6位为"+car.getVin()+"的"+car.getCarName()+"，没有在规定的"+tempIdentityTime+"分钟内从临时展厅出库，被系统自动挂起，请到出入库进行解挂。超出规定时间"+intervalTime+"分钟。";
    	}
    	return content;
    }
	
    
	private String getPushContent(Car car,int type) {
		String PUSH_LICENSEPLATE_STR = "【临时进出通知】库存车辆（｛车辆名称｝，｛车牌号码｝）在｛当前系统时间｝｛进出状态｝，设定的临时进出时间为｛临时的进出时间｝。";
		String PUSH_VIN_STR = "【临时进出通知】库存车辆（｛车辆名称｝，｛VIN码｝）在｛当前系统时间｝｛进出状态｝，设定的临时进出时间为｛临时的进出时间｝。";
		String CAR_NAME = "车辆名称";
		String CAR_NUMBER = "车牌号码";
		String CAR_VIN = "VIN码";
		String SYSTEM_TIME = "当前系统时间";
		String STORAGEENTER_TIME = "临时的进出时间";
		String STORAGEENTER_STATUS = "进出状态";
		String BEFOREBRACE = "｛";
		String LATERBRACE = "｝";
		String contentStr = "";
		
		String carInfo = "";
		//车牌号不为空
		if(!StringUtil.isNullOrBlank(car.getLicensePlate()))
		{
			carInfo = car.getLicensePlate();
			carInfo = carInfo.substring(carInfo.length()-5, carInfo.length());
			contentStr = PUSH_LICENSEPLATE_STR;
		} else{//车牌号为空
			carInfo = car.getVin();
			carInfo = carInfo.substring(carInfo.length()-6, carInfo.length());			
			contentStr = PUSH_VIN_STR;
		}
		contentStr = contentStr.replaceAll(BEFOREBRACE, "").replaceAll(LATERBRACE, "");

		//系统时间
		String sysTime = DateUtil.getCurrentTime1();
		String storageTime = "";
		String enterTime = "";
		//临时进出时间
		String temStorageEnterTime = "";
		if(car.getTmpStorageTime() != null){
			storageTime = StringUtil.getTimeByTimeStamp(car.getTmpStorageTime());
		}
		if(car.getTmpEnterTime() != null){
			enterTime = StringUtil.getTimeByTimeStamp(car.getTmpEnterTime());
		}
		temStorageEnterTime = storageTime + " ~ " + enterTime;
		String storageEnterStatus = "";
		//进出状态
		if(type == 1){//入库情况
			storageEnterStatus = "进入展厅";
		}else if(type == 2){//出库情况
			storageEnterStatus = "离开展厅";
		}
		String carName = "";
		if(!StringUtil.isNullOrBlank(car.getCarName())){
			carName = car.getCarName();
		}
		contentStr = contentStr.replaceAll(CAR_NAME, carName).replaceAll(CAR_NUMBER, carInfo)
		.replaceAll(CAR_VIN, carInfo).replaceAll(SYSTEM_TIME, sysTime).replaceAll(STORAGEENTER_STATUS, storageEnterStatus).replaceAll(STORAGEENTER_TIME, temStorageEnterTime); 
		
		return contentStr;
	}
	
	private String getFinancialPushContent(Car car,int type) {
		String PUSH_LICENSEPLATE_STR = "【金融车辆进出通知】库存车辆（｛车辆名称｝，｛车牌号码｝）在｛当前系统时间｝{进出状态}";
		String PUSH_VIN_STR = "【金融车辆进出通知】库存车辆（｛车辆名称｝，｛VIN码｝）在｛当前系统时间｝{进出状态}";
		String CAR_NAME = "车辆名称";
		String CAR_NUMBER = "车牌号码";
		String CAR_VIN = "VIN码";
		String SYSTEM_TIME = "当前系统时间";
		String STORAGEENTER_TIME = "临时的进出时间";
		String STORAGEENTER_STATUS = "进出状态";
		String BEFOREBRACE = "｛";
		String LATERBRACE = "｝";
		String contentStr = "";
		
		String carInfo = "";
		//车牌号不为空
		if(!StringUtil.isNullOrBlank(car.getLicensePlate()))
		{
			carInfo = car.getLicensePlate();
			carInfo = carInfo.substring(carInfo.length()-5, carInfo.length());
			contentStr = PUSH_LICENSEPLATE_STR;
		} else{//车牌号为空
			carInfo = car.getVin();
			carInfo = carInfo.substring(carInfo.length()-6, carInfo.length());			
			contentStr = PUSH_VIN_STR;
		}
		contentStr = contentStr.replaceAll(BEFOREBRACE, "").replaceAll(LATERBRACE, "");

		//系统时间
		String sysTime = DateUtil.getCurrentTime1();
		String storageTime = "";
		String enterTime = "";
		//临时进出时间
		String temStorageEnterTime = "";
		if(car.getTmpStorageTime() != null){
			storageTime = StringUtil.getTimeByTimeStamp(car.getTmpStorageTime());
		}
		if(car.getTmpEnterTime() != null){
			enterTime = StringUtil.getTimeByTimeStamp(car.getTmpEnterTime());
		}
		temStorageEnterTime = storageTime + " ~ " + enterTime;
		String storageEnterStatus = "";
		//进出状态
		if(type == 1){//入库情况
			storageEnterStatus = "进入展厅";
		}else if(type == 2){//出库情况
			storageEnterStatus = "离开展厅";
		}
		String carName = "";
		if(!StringUtil.isNullOrBlank(car.getCarName())){
			carName = car.getCarName();
		}
		contentStr = contentStr.replaceAll(CAR_NAME, carName).replaceAll(CAR_NUMBER, carInfo)
		.replaceAll(CAR_VIN, carInfo).replaceAll(SYSTEM_TIME, sysTime).replaceAll(STORAGEENTER_STATUS, storageEnterStatus).replaceAll(STORAGEENTER_TIME, temStorageEnterTime); 
		
		return contentStr;
	}
	
	
	private boolean isComparedResult(Timestamp currentTime,Car car,int type){
		boolean result = false;
		if(type == 1){//如果车辆存在并且车辆挂起状态为“1：是” 并且 （当前系统时间小于临时进出开始时间（tmpStorageTime）或者 大于 临时进出结束时间（tmpEnterTime））
			if(car.getTmpStorageTime() == null && car.getTmpEnterTime() == null) result = true;
		    else if(car.getStorageTime() != null && currentTime.before(car.getStorageTime())) result = true;
			else if(car.getTmpEnterTime() != null && currentTime.after(car.getTmpEnterTime())) result = true;
		}if(type == 2){
			if(car.getStorageTime() == null){
				result = true;
			}else{
				if(currentTime.after(car.getStorageTime()) || currentTime.equals(car.getStorageTime())){
					result = true;
				}
			}
			if(car.getTmpEnterTime() != null){
				if(currentTime.before(car.getTmpEnterTime()) || currentTime.equals(car.getTmpEnterTime())){
					result = true;
				}
			}
		}
		return result;
	}
	
	
	private int getTmpIdentityTime(){
		try {
			String time = Registry.getConfigFromDb("tmpIdentityTime");
			return Integer.parseInt(time);
		} catch (Exception e) {
			return 0;
		}
	}
	
	private boolean isCheckTmpIdentityTime(Car car){
		int tmpTime = getTmpIdentityTime();
		return getIntervalTime(new Date(),car.getInsertTime()) > tmpTime;
	}
	
	private void callApiTransferDataSyn210(Car car,Member member){
		String manager = Registry.getConfigFromDb("manager");
		MobileMessage message = new MobileMessage();
		message.putValue("Serial", car.getSerial());
		message.setMessage("【TMS】新增入库（库存存在情况的更新保存）【车代办】同步,Serial为#Serial#");
		TransferDataSyn000210Bo api = new TransferDataSyn000210Bo();
		api.setMobileMessage(message);
		api.setSerial(car.getSerial());
		api.setManager(manager);
		api.setMemberId(member.getMemId()+"");
		api.setPushMessage(getPushContent(car,member));
		api.setMarketNo(TmsConstants.MARKET_NO);
		PullingExecutor.getInstance().submit(api);
	}
}
